﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;

namespace UpdateSoon
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {

        System.Diagnostics.Process getMatchProgress(IEnumerable<System.Diagnostics.Process> l, string processName) 
        {
            return l.FirstOrDefault(i => i.ProcessName == processName);
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            #region 注册事件 - 捕获未处理的异常

            // 主线程
            this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);

            // 非主线程
            System.AppDomain.CurrentDomain.UnhandledException += new System.UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            #endregion

            string caption = "UpdateSoon 提示您";

            string[] args = e.Args;

            string progressName = args[0];

            System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
            var processList = System.Diagnostics.Process.GetProcesses().ToList();
            var matchProcess = getMatchProgress(processList, progressName);

            int tryCount = 0;

            // 等待进程关闭
            while (matchProcess != null)
            {
                MessageBoxResult dr = MessageBoxResult.Cancel;

                if (tryCount == 0)
                {
                    dr = MessageBox.Show($"{progressName}\r\n新版本已准备就绪，\r\n确认更新？", caption, MessageBoxButton.OKCancel, MessageBoxImage.Question, MessageBoxResult.OK);
                }
                else 
                {
                    dr = MessageBox.Show($"{progressName}正在运行中，\r\n确认退出并重试更新？", caption, MessageBoxButton.OKCancel, MessageBoxImage.Question, MessageBoxResult.OK);
                }

                if (dr == MessageBoxResult.Cancel) 
                {
                    Current.Shutdown();
                    return;
                }

                matchProcess.Kill();

                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
                processList = System.Diagnostics.Process.GetProcesses().ToList();
                matchProcess = getMatchProgress(processList, progressName);

                tryCount++;
            }

            string zipFilePath = string.Empty;
            string sourceDir = string.Empty;
            string targetDir = string.Empty;
            System.IO.FileInfo fi = null;
            try
            {
                zipFilePath = args[1];
                fi = new System.IO.FileInfo(zipFilePath);
                if (fi.Exists == false)
                {
                    throw new Exception($"下载zip文件不存在。{zipFilePath}");
                }
                sourceDir = fi.Directory.FullName;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, caption, MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                Current.Shutdown();
                return;
            }

            try
            {
                targetDir = args[2];
                if (string.IsNullOrEmpty(targetDir)) 
                {
                    throw new Exception("args[2]为空值，请传值给targetDir。");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, caption, MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                Current.Shutdown();
                return;
            }

            try
            {
                SharpZipLibUtils.Unzip(zipFilePath, sourceDir);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, caption, MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
                Current.Shutdown();
                return;               
            }   
            
            fi.Delete();

            DirectoryUtils.Copy(sourceDir, targetDir);

            MessageBox.Show($"{progressName}更新完毕。", caption, MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);

            Current.Shutdown();
        }



        #region 捕获未处理的异常

        /// <summary>
        /// 主线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                HandleException("DispatcherUnhandledException", e.Exception);
                e.Handled = true;
            }
            catch (Exception ex)
            {
#if DEUBG
                string msg = $"HandleException 发生异常。{ex.Message}";
                System.Diagnostics.Debug.WriteLine(msg);
                System.Diagnostics.Debugger.Break();
#endif
                throw ex;
            }
        }

        /// <summary>
        /// 非主线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                if (e.ExceptionObject is System.Exception)
                {
                    HandleException("CurrentDomain.UnhandledException", e.ExceptionObject as System.Exception);
                }
            }
            catch (Exception ex)
            {
#if DEUBG
                string msg = $"HandleException 发生异常。{ex.Message}";
                System.Diagnostics.Debug.WriteLine(msg);
                System.Diagnostics.Debugger.Break();
#endif
                throw ex;
            }
        }

        public static void HandleException(string from, Exception ex)
        {
            string crashDir = System.IO.Path.Combine(Environment.CurrentDirectory, "crash_UpdateSoon");
            string filePath = System.IO.Path.Combine(crashDir, $"{DateTime.Now.ToString("yyyyMMdd")}.log");
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.AppendAllText(filePath, ex.ToString());
            }
            else
            {
                System.IO.File.WriteAllText(filePath, ex.ToString());
            }

            MessageBox.Show
            (
                caption: "捕获到以下错误，请与管理员联系以获取帮助。",
                messageBoxText: $"在 {from} 捕获到以下错误\r\n{ex.Message}"
            );
        }

        public static bool IsMainThread
        {
            get
            {
                return System.Threading.Thread.CurrentThread.IsBackground == false;
            }
        }

        public static void BeginInvokeOnMainThread(Action action, System.Windows.Threading.DispatcherPriority dp = System.Windows.Threading.DispatcherPriority.DataBind)
        {
            if (IsMainThread)
            {
                action();
            }
            else
            {
                // 学习为什么 .net core 没有 BeginInvoke
                Current.Dispatcher.BeginInvoke(action, dp);
            }
        }

        #endregion
    }
}
